package com.sesame.controller;

import com.sesame.bean.Column;
import com.sesame.bean.DbInfo;
import com.sesame.bean.Table;
import com.sesame.core.Generate;
import com.sesame.service.DBService;
import com.sesame.service.DBServicePool;
import com.sesame.util.DateUtil;
import com.sesame.util.TableUtil;
import com.sesame.util.Theme;
import kim.sesame.framework.entity.GMap;
import kim.sesame.framework.exception.BusinessException;
import kim.sesame.framework.utils.StringUtil;
import kim.sesame.framework.utils.ZipCompressor;
import kim.sesame.framework.web.context.SpringContextUtil;
import kim.sesame.framework.web.controller.AbstractWebController;
import kim.sesame.framework.web.response.Response;
import kim.sesame.framework.web.util.FileUtil;
import lombok.extern.apachecommons.CommonsLog;
import net.sf.json.JSONArray;
import org.springframework.cglib.beans.BulkBeanException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 数据
 *
 * @author wangjianghai
 * @date 2016年3月31日 上午10:42:30
 * @Description:
 */
@CommonsLog
@Controller
@RequestMapping("/db")
public class DbController extends AbstractWebController {

    @RequestMapping("/init")
    @ResponseBody
    public void init(HttpServletRequest request) {
        log.info(">>>>>>init theme start");
        Theme.themes.stream().forEach(s -> {
            log.info(s);
        });
        log.info(">>>>>>init theme end");
    }

    /**
     * 验证数据库连接并取得所有的表名
     *
     * @author wangjianghai @date 2016年3月31日 下午2:11:25 @Title
     * conn @Description @param bean @param request @return int @throws
     */
    @RequestMapping("/conn")
    @ResponseBody
    public Response conn(DbInfo bean, HttpServletRequest request) {

        //log.info("<<<<<<<<<<<<<<<<<<<<<DbController"+DbController.class.getResource("DbController.java").getFile());
        log.info(">>>>>>>>>>>>>>>>>>>resourcePath:" + Theme.resourcePath);
        bean.viferyDbType();
        Connection conn = DBService.getConn(bean);
        if (conn == null) {
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>数据库连接失败");
            request.getSession().setAttribute("dbinfo", null);
            throw new BusinessException("数据库连接失败");
        } else {
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>数据库连接成功");
            bean.setTables(DBServicePool.getDbService(bean.getDb_driver()).getTables(conn));
            request.getSession().setAttribute("dbinfo", bean);

            // 获取所有的主题名称
            request.getSession().setAttribute("themes", Theme.themes);

            return returnSuccess();
        }
    }

    /**
     * 查询表
     */
    @RequestMapping("/searchTable")
    @ResponseBody
    public Response searchTable(String name, HttpServletRequest request) {

        List<Table> tables = new ArrayList<Table>();

        DbInfo bean = (DbInfo) request.getSession().getAttribute("dbinfo");
        if (bean == null) {
            return returnSuccess(tables);
        }
        if (StringUtil.isEmpty(name)) {
            return returnSuccess(bean.getTables());
        }
        for (Table t : bean.getTables()) {
            if (t.getTableName().toLowerCase().indexOf(name.toLowerCase()) >= 0) {
                tables.add(t);
            } else if (t.getComment().indexOf(name) >= 0) {
                tables.add(t);
            }
        }
        return returnSuccess(tables);
    }

    /**
     * 查询表详情 老版本,
     */
    @RequestMapping("/searchTableDetail")
    @ResponseBody
    public List<Column> searchTableDetail(String tableName, HttpServletRequest request) {

        List<Column> list = new ArrayList<Column>();

        DbInfo bean = (DbInfo) request.getSession().getAttribute("dbinfo");
        if (bean == null || StringUtil.isEmpty(tableName)) {
            return list;
        }
        Connection conn = DBService.getConn(bean);

        list = DBServicePool.getDbService(bean.getDb_driver()).parseTable(tableName, conn);

        DBService.closeConn(conn);
        return list;
    }

    /**
     * 查询表详情 页面转发,新版本
     */
    @RequestMapping("/tableDetail")
    public String tableDetail(String tableName, HttpServletRequest request, ModelMap model) {

        List<Column> list = null;

        DbInfo bean = (DbInfo) request.getSession().getAttribute("dbinfo");
        if (bean == null || StringUtil.isEmpty(tableName)) {
            // 修改的原方法,这里不做任何修改
            list = new ArrayList<Column>();
        } else {
            Connection conn = DBService.getConn(bean);
            list = DBServicePool.getDbService(bean.getDb_driver()).parseTable(tableName, conn);
            DBService.closeConn(conn);
        }
        model.put("list", list);

        return "tableDetail";
    }

    @RequestMapping("/generate")
    public void generate(DbInfo bean, HttpServletRequest request, HttpServletResponse response) {

        String basePath = getFileDir("download");
        String systime = DateUtil.formatString(new Date(), "yyyyMMddHHmmss");
        String fileDir = bean.getFk_type() + "_" + systime; // 文件夹的名字

        generateCode(bean, basePath, fileDir);

        try {

            String outPath = basePath + "/" + fileDir;

            // 文件压缩
            ZipCompressor zc = new ZipCompressor(outPath + ".zip");
            zc.compress(outPath);

            // 实现文件下载
            response.setContentType("text/plain");
            response.setHeader("Location", fileDir + ".zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileDir + ".zip");
            OutputStream outputStream = response.getOutputStream();
            InputStream inputStream = new FileInputStream(outPath + ".zip");

            byte[] b = new byte[inputStream.available()];
            inputStream.read(b);
            outputStream.write(b);

            outputStream.flush();
            outputStream.close();
            inputStream.close();

            // 删除源文件
            FileUtil.clearFiles(new File(outPath));
            FileUtil.clearFiles(new File(outPath + ".zip"));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public String getFileDir(String name) {
        String basePath = SpringContextUtil.getCurrentPath() + "/" + name;
        File f = new File(basePath);
        if (!f.exists()) {
            f.mkdirs();
        }
        return basePath;
    }

    /**
     * 预览
     *
     * @param bean
     * @param request
     * @param response void
     * @author wangjianghai
     * @date 2017年5月10日 下午10:48:24
     * @Title preview
     * @Description
     */
    @RequestMapping("/preview")
    @ResponseBody
    public Response preview(DbInfo bean, HttpServletRequest request, HttpServletResponse response) {

        String basePath = getFileDir("preview");// preview
        String systime = DateUtil.formatString(new Date(), "yyyyMMddHHmmss");
        String fileDir = bean.getFk_type() + "_" + systime; // 文件夹的名字

        generateCode(bean, basePath, fileDir);

        String outPath = basePath + "/" + fileDir;
        request.getSession().setAttribute("outPath", outPath);
        request.getSession().setAttribute("fileDir", fileDir);

        return returnSuccess();
    }

    @RequestMapping("/getnode")
    @ResponseBody
    public JSONArray getnode(boolean flg, HttpServletRequest request, HttpServletResponse response, ModelMap model) {

        String outPath = (String) request.getSession().getAttribute("outPath");
        String fileDir = (String) request.getSession().getAttribute("fileDir");
        List<GMap> listAll = new ArrayList<GMap>();
        GMap map = GMap.newMap();

        map.putAction("name", fileDir);
        map.putAction("spread", true);

        File file = new File(outPath);
        List<GMap> list = searchfile(file, flg);
        map.putAction("children", list);

        listAll.add(map);

        JSONArray jsonarr = JSONArray.fromObject(listAll);
        System.out.println(jsonarr.toString());

        return jsonarr;
    }

    public static List<GMap> searchfile(File file, boolean flg) {
        List<GMap> listAll = new ArrayList<GMap>();
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            GMap map = GMap.newMap();
            map.putAction("name", f.getName());

            if (f.isDirectory()) {
                map.putAction("spread", flg);
                List<GMap> list = searchfile(f, flg);
                map.putAction("children", list);
            } else if (f.isFile()) {
                map.putAction("filepath", f.getAbsolutePath());
            }
            listAll.add(map);
        }
        return listAll;
    }

    /**
     * 读取文件
     *
     * @param path
     * @return String
     * @author wangjianghai
     * @date 2017年5月11日 上午1:29:23
     * @Title getfilecontent
     * @Description
     */
    @RequestMapping("/getfilecontent")
    @ResponseBody
    public List<String> getfilecontent(String path) {

        List<String> list;
        try {
            list = org.apache.commons.io.FileUtils.readLines(new File(path), "UTF-8");
        } catch (IOException e) {
            list = new ArrayList<String>();
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 删除预览锁产生的文件
     *
     * @param request
     * @return int
     * @author wangjianghai
     * @date 2017年5月11日 下午9:41:14
     * @Title deletedir
     * @Description
     */
    @RequestMapping("/deletedir")
    @ResponseBody
    public int deletedir(HttpServletRequest request) {

        String outPath = (String) request.getSession().getAttribute("outPath");
        String fileDir = (String) request.getSession().getAttribute("fileDir");

        // System.out.println(outPath);
        // System.out.println(fileDir);
        //
        FileUtil.clearFiles(new File(outPath));

        return 1;
    }

    private void generateCode(DbInfo bean, String basePath, String fileDir) {

        String path = basePath + "/" + fileDir + "/java";
        String path_page = basePath + "/" + fileDir + "/page";
        String path_js = basePath + "/" + fileDir + "/js";

        Connection conn = DBService.getConn(bean);

        HashMap<String, Object> params = null; // 封装参数
        String entityPackage = ""; // 实体的包名
        String controllerPackage = ""; // controller
        String servicePackage = ""; // service
        String daoPackage = ""; // dao
        for (Table t : bean.getTables()) {

            params = new HashMap<String, Object>();
            if (t.getClassName() == null || t.getClassName().equals("")) {
                t.setClassName(TableUtil.hump(t.getClassName(), true));
            }
            if (t.getPackageName() == null || t.getPackageName().equals("")) {
                t.setPackageName(t.getPackageName().toLowerCase());
            }
            entityPackage = bean.getBasePackageName() + "." + t.getPackageName() + ".bean";
            controllerPackage = bean.getBasePackageName() + "." + t.getPackageName() + ".controller";
            servicePackage = bean.getBasePackageName() + "." + t.getPackageName() + ".service";
            daoPackage = bean.getBasePackageName() + "." + t.getPackageName() + ".dao";

            List<Column> list = DBServicePool.getDbService(bean.getDb_driver()).parseTable(t.getTableName(), conn);
            if (list == null || list.size() == 0) {
                System.out.println("**********  " + t.getTableName() + " 表不存在,注意表名区分大小写    *******************************");
                continue;
            }
            String fileAll = TableUtil.fileAll(list);
            params.put("fileAll", fileAll);
            String fileAllSelect = TableUtil.fileAllSelect(list);
            params.put("fileAllSelect", fileAllSelect);

            params.put("packageName", t.getPackageName());
            params.put("entityPackage", entityPackage);
            params.put("controllerPackage", controllerPackage);
            params.put("servicePackage", servicePackage);
            params.put("daoPackage", daoPackage);

            params.put("tableName", t.getTableName());//
            params.put("className", t.getClassName());//
            params.put("author", bean.getAuthor());// 注释上的作者
            params.put("systime", DateUtil.formatString(new Date()));// 注释上的时间
            params.put("list", list);// 表结构
            params.put("fk", TableUtil.getPrimary(list));// 表的主键
            params.put("fk_java", TableUtil.hump(params.get("fk").toString(), false));// 表的主键
//            params.put("suffix_page", bean.getSuffix_page());//

            // params.put("serviceImpl", t.isServiceImpl()));//
            params.put("add", t.isAdd());//
            params.put("delete", t.isDelete());//
            params.put("update", t.isUpdate());//
            params.put("select", t.isSelect());//
            params.put("selectPage", t.isSelectPage());//
            params.put("selectList", t.isSelectList());//
            params.put("tableComment", t.getComment());// 表注释

            Generate.entity(params, bean.getFk_type(), path);// 生成实体类
            Generate.controller(params, bean.getFk_type(), path); // 生成controller
            Generate.service(params, bean.getFk_type(), path); // 生成 service
            Generate.dao(params, bean.getFk_type(), path); // 生成dao

            if (t.isPage()) {
                String pageType = "html";
                Generate.page(params, bean.getFk_type(), path_page, "list", pageType); // 生成list.html
                Generate.page(params, bean.getFk_type(), path_page, "add", pageType); // 生成add.html
                Generate.page(params, bean.getFk_type(), path_page, "edit", pageType); // 生成edit.html

                Generate.script(params, bean.getFk_type(), path_js, "list");
                Generate.script(params, bean.getFk_type(), path_js, "add");
                Generate.script(params, bean.getFk_type(), path_js, "edit");
            }

        } // for
        // 循环完之后关闭数据库连接
        DBService.closeConn(conn);
    }
}
